#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "NetBuf.h"
#include "Packet.h"

void SimpleBuf::Tidy()
{
	assert(nHead <= nTail);

	memmove(szBUF,szBUF+nHead,nTail - nHead);
	nTail = nTail - nHead;
	nHead = 0; 
}

int SimpleBuf::GetSpace() const
{
	assert(nHead <= nTail);

	return BUFF_SIZE - nTail;
}

int SimpleBuf::GetLength() const
{
	assert(nHead <= nTail);

	return nTail - nHead;
}

char* SimpleBuf::GetHeadBuf()
{
	assert(nHead <= nTail);

	return szBUF + nHead;
}

char* SimpleBuf::GetTailBuf()
{
	assert(nHead <= nTail);

	return szBUF + nTail;
}


bool SimpleBuf::Write(const char* pBuf,int nSize )
{
	int nSpace = GetSpace();
	if (nSpace >= nSize)
	{
		memcpy(GetTailBuf(),pBuf,nSize);
		nTail += nSize;
		assert(nHead <= nTail);

		return true;
	}
	else
		return false;
}

bool SimpleBuf::Read( char* pBuf,int nSize )
{
	int nLength = GetLength();
	if (nLength >= nSize)
	{
		memcpy(pBuf,GetHeadBuf(),nSize);
		nHead += nSize;
		assert(nHead <= nTail);
		return true;
	}
	else
		return false;
}

SimpleBuf::SimpleBuf()
{
	nHead = 0;
	nTail = 0;
	memset(szBUF,0,BUFF_SIZE);
}

void SimpleBuf::MoveTail(int nCount)
{
	assert(nTail + nCount <= BUFF_SIZE);
	nTail += nCount;
}

void SimpleBuf::MoveHead( int nCount )
{
	assert(nHead + nCount <= nTail);
	nHead += nCount;

}

void NetBuffer::PushBackPacket( Packet* pPacket )
{
	Auto_locker lock(m_packetCritical);
	m_deqPacket.push_back(pPacket);
}

Packet* NetBuffer::PopFrontPacket()
{
	Auto_locker lock(m_packetCritical);
	if (m_deqPacket.empty())
	{
		return NULL;
	}
	Packet* pPacket = m_deqPacket.front();
	m_deqPacket.pop_front();
	return pPacket;
}

Packet* NetBuffer::PopBackPacket()
{
	Auto_locker lock(m_packetCritical);
	if (m_deqPacket.empty())
	{
		return NULL;
	}
	Packet* pPacket = m_deqPacket.front();
	m_deqPacket.pop_back();
	return pPacket;

}


void NetBuffer::OnRecived( std::size_t transferred )
{
	m_simpleBuff.MoveTail(transferred);

	int nLenght = m_simpleBuff.GetLength();
	while(nLenght > sizeof(Head))
	{
		Head* pHead = (Head*)m_simpleBuff.GetHeadBuf();
		if (pHead->nSize > nLenght)
		{
			break;
		}
		m_simpleBuff.MoveHead(sizeof(Head));
		Packet* pPacket = Packet::Create(pHead->nType);
		if (pPacket == NULL)
			return ;

		pPacket->read(m_simpleBuff);
		PushBackPacket(pPacket);

		nLenght = m_simpleBuff.GetLength();
	}
	m_simpleBuff.Tidy();

}

void NetBuffer::OnSended( std::size_t transferred )
{
	m_simpleBuff.MoveHead(transferred);
	m_simpleBuff.Tidy();
}


NetBuffer::NetBuffer()
{
	memset(&m_wsaBuff,0,sizeof(m_wsaBuff));
}
NetBuffer::~NetBuffer()
{
	DEQ_PACKET::iterator _iter = m_deqPacket.begin();
	for (; _iter != m_deqPacket.end(); ++_iter)
	{
		if (*_iter)
		{
			delete (*_iter);
		}
	}
	m_deqPacket.clear();

}
WSABUF& NetBuffer::GetReceiveBuff()
{
	m_wsaBuff.buf = m_simpleBuff.GetTailBuf();
	m_wsaBuff.len = m_simpleBuff.GetSpace();

	return m_wsaBuff;
}

WSABUF& NetBuffer::GetSendBuff()
{
	Packet* pPacket = PopFrontPacket();
	while(pPacket)
	{
		if (m_simpleBuff.GetSpace() < sizeof(Head))
		{
			m_simpleBuff.Tidy();
			if (m_simpleBuff.GetSpace() < sizeof(Head))
			{
				break;
			}
		}

		int nOldPos = m_simpleBuff.nTail;
		m_simpleBuff.MoveTail(sizeof(Head));

		if (!pPacket->write(m_simpleBuff))
		{
			m_simpleBuff.nTail -= sizeof(Head);
		}

		Head head;
		head.nPrefiex = Packet_Prefix;
		head.nType = pPacket->GetType();
		head.nSize = m_simpleBuff.nTail - nOldPos;
		memcpy(m_simpleBuff.szBUF+nOldPos,&head,sizeof(head));

		SAFE_DELETE(pPacket);
		pPacket = PopFrontPacket();
	}
	m_wsaBuff.buf = m_simpleBuff.GetHeadBuf();
	m_wsaBuff.len = m_simpleBuff.GetLength();

	return m_wsaBuff;
}

